/*  ------------------------------------------------------------------------
	 NQ Common Services Library
	 
	 Homepage: http://www.awzhome.de/
	 ------------------------------------------------------------------------
	 
	 The contents of this file are subject to the Mozilla Public License
	 Version 1.1 (the "License"); you may not use this file except in
	 compliance with the License. You may obtain a copy of the License at
	 http://www.mozilla.org/MPL/
	 
	 Software distributed under the License is distributed on an "AS IS"
	 basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
	 License for the specific language governing rights and limitations
	 under the License.
	
	 The Original Code is code of NQ Common Services Library.

	 The Initial Developer of the Original Code is Andreas Weizel.
	 Portions created by the Initial Developer are
	 Copyright (C) 2006-2012 Andreas Weizel. All Rights Reserved.
	 
	 Contributor(s): (none)
	 
	 Alternatively, the contents of this file may be used under the terms
	 of the GNU General Public License Version 2.0 or later (the "GPL"),
	 or the GNU Lesser General Public License Version 2.1 or later (the
	 "LGPL"), in which case the provisions of the GPL or the LGPL are
	 applicable instead of those above. If you wish to allow use of your
	 version of this file only under the terms of the GPL or the LGPL and
	 not to allow others to use your version of this file under the MPL,
	 indicate your decision by deleting the provisions above and replace
	 them with the notice and other provisions required by the GPL or the
	 LGPL. If you do not delete the provisions above, a recipient may use
	 your version of this file under the terms of any of the MPL, the GPL
	 or the LGPL.
	 ------------------------------------------------------------------------
*/

using System;
using System.Collections.Generic;
using System.Text;
using AWZhome.NQ.Core;
using AWZhome.NQ.Core.Fluent;
using System.IO;
using System.Xml.Serialization;
using System.Xml;
using AWZhome.NQ.CommonServices.Visual;
using System.Windows.Controls.Primitives;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Linq;

namespace AWZhome.NQ.CommonServices
{

	[NQExportedService]
	internal class BarService : Services.IBarService
	{
		private class NQBarItemDependency : IBarItemDependency
		{
			private string key = String.Empty;
			private bool isVisible = true;

			public NQBarItemDependency(string key, bool isVisible)
			{
				this.key = key;
				this.isVisible = isVisible;
			}

			#region INQBarItemDependency Members

			public string Key
			{
				get
				{
					return key;
				}
			}

			public bool IsVisible
			{
				get
				{
					return isVisible;
				}
			}

			#endregion
		}

		private IPersistManager _persistService;
		private IContainer _containerService;

		private bool _barServiceInit = false;
		private NQBarBand _mainMenuBand = null;
		private string _context = String.Empty;

		private BarHost _barHost = null;
		private StatusBar _statusBar = null;

		private Dictionary<string, NQBarBand> _bands = new Dictionary<string, NQBarBand>();
		private Dictionary<string, NQBarItem> _bandItems = new Dictionary<string, NQBarItem>();
		private Dictionary<string, NQStatusBarPanel> _statusPanels = new Dictionary<string, NQStatusBarPanel>();

		private Dictionary<string, List<IBarItemDependency>> _sessBandList = new Dictionary<string, List<IBarItemDependency>>();
		private Dictionary<string, List<IBarItemDependency>> _viewBandList = new Dictionary<string, List<IBarItemDependency>>();
		private Dictionary<string, List<IBarItemDependency>> _sessItemList = new Dictionary<string, List<IBarItemDependency>>();
		private Dictionary<string, List<IBarItemDependency>> _viewItemList = new Dictionary<string, List<IBarItemDependency>>();
		private List<string> _hiddenItems = new List<string>();

		#region INQBarService Members

		public event System.EventHandler<BarItemClickedEventArgs> ItemClicked;

		public bool PreProcessMessage(object msg)
		{
			return true;
		}

		public void InitBarService(object parent, string context, IContainer containerService)
		{
			if (_barServiceInit)
				return;

			this._context = context;
			_barServiceInit = true;
			_containerService = containerService;

			// Get instance of PersistService
			_persistService = ServiceCore
				.Get<Services.IPersistService>()
				.Instance;

			// Create a BarHost and place it in the containerService
			_barHost = new BarHost();
			_barHost.Visibility = Visibility.Visible;
			_barHost.Margin = new Thickness(0, 0, 0, 0);

			if (containerService != null)
			{
				((Grid) containerService.ClientAreaObject).Children.Add(_barHost);

				// Change container's content area
				containerService.ClientAreaObject = _barHost.GridClientContainer;
			}
			else
			{
				Panel clientArea = parent as Panel;
				if (clientArea != null)
				{
					clientArea.Children.Add(_barHost);
				}
			}

			// Get item invisibility information
			IList<ConfigData> hiddenItems = _persistService.GetListSetting("NQCS", "hiddenItems_" + context, true);
			if (hiddenItems != null)
			{
				_hiddenItems.AddRange(hiddenItems.Select(value => value.AsString()));
			}
		}

		public void CreateMenuBar()
		{
			if (_barHost != null)
			{
				_mainMenuBand = new NQBarBand(this, BarBandType.MenuBand, "MainMenu");
				_mainMenuBand.BandVisible = true;
				_mainMenuBand.BandLine = 0;
			}
		}

		public void CreateStatusBar()
		{
			if (!_barServiceInit || (_statusBar != null))
				return;

			// Make the StatusBar of the BarHost visible
			_statusBar = _barHost.StatusBar;
			_statusBar.Visibility = Visibility.Visible;
		}

		public void LoadBarSettings()
		{
			string mainmenuDirection = "t";

			// Iterate through all bands at the top
			IList<ConfigData> barSetting = _persistService.GetListSetting("NQCS", "toolBands_" + _context, true);
			if (barSetting != null)
			{
				foreach (ConfigData data in barSetting)
				{
					string[] topBarsArray = data.AsString().Split('|');
					List<string> topBars = new List<string>(topBarsArray);
					// We need 6 elements in the array
					for (int i = topBarsArray.Length; i < 6; i++)
					{
						topBars.Add(String.Empty);
					}

					if (_bands.ContainsKey(topBars[0]))
					{
						NQBarBand band = _bands[topBars[0]];
						if (band.BandType == BarBandType.ToolBand)
						{
							band.DockDirection = DirectionFromSettingChar(topBars[3]);
							band.BandVisible = (topBars[4] == "1");
							int bandIndex = 0;
							int bandRow = 0;
							double bandWidth = 0;
							int.TryParse(topBars[1], out bandIndex);
							int.TryParse(topBars[2], out bandRow);
							double.TryParse(topBars[5], out bandWidth);
							band.ToolBar.BandIndex = bandIndex;
							band.ToolBar.Band = bandRow;
							if (bandWidth > 0)
							{
								band.ToolBar.Width = bandWidth;
							}
							//band.HideAlways = IsBandDependent(topBars[0]);
							//band.ToolBar = (Point) (new NQPersistData(topBars[1] + "|" + topBars[2]));
						}
					}
					else if (topBars[0] == _mainMenuBand.BandKey)
					{
						mainmenuDirection = topBars[3];
						//mainmenuLocation = new NQPersistDataBasic(topBars[1] + "|" + topBars[2]);
						_mainMenuBand.DockDirection = this.DirectionFromSettingChar(mainmenuDirection);
						int bandIndex = 0;
						int.TryParse(topBars[1], out bandIndex);
						_mainMenuBand.ToolBar.BandIndex = bandIndex;
					}
				}
			}
		}

		public void SaveBarSettings()
		{
			List<ConfigData> barSetting = new List<ConfigData>();

			// Iterate through all bands and save information about them
			foreach (NQBarBand band in _bands.Values)
			{
				if (band.BandType == BarBandType.ToolBand)
				{
					barSetting.Add(new ConfigData().FromString(
						band.BandKey
							+ "|" + band.ToolBar.BandIndex //band.ToolStrip.Location.X.ToString()
							+ "|" + band.ToolBar.Band // band.ToolStrip.Location.Y.ToString()
							+ "|" + this.SettingCharFromDirection(band.DockDirection)
							+ "|" + (band.BandVisible ? "1" : "0")
							+ "|" + band.ToolBar.Width.ToString("#####0")
						));
				}
			}

			// Save menu bar settings
			barSetting.Add(new ConfigData().FromString(
						_mainMenuBand.BandKey
							+ "|" + "0" // _mainMenuBand.ToolStrip.Location.X.ToString()
							+ "|" + "0" // _mainMenuBand.ToolStrip.Location.Y.ToString()
							+ "|" + SettingCharFromDirection(_mainMenuBand.DockDirection)
							+ "|1|0"
						));

			// Save the list
			_persistService.SetListSetting("NQCS", "toolBands_" + _context, barSetting, true);

			// Save all items hidden by user
			List<ConfigData> hiddenItems = new List<ConfigData>();
			foreach (KeyValuePair<string, NQBarItem> itementry in _bandItems)
			{
				if (!itementry.Value.ItemVisible)
				{
					hiddenItems.Add(new ConfigData().FromString(itementry.Key));
				}
			}
			_persistService.SetListSetting("NQCS", "hiddenItems_" + _context, hiddenItems, true);
		}

		public IBarItem CreateItem(string itemKey, BarItemType itemType)
		{
			if (_bandItems.ContainsKey(itemKey))
			{
				// This item key already exists, throw an exception!
				throw new BarDefinitionException("Bar item with key '" + itemKey + "' already exists.", itemKey);
			}

			NQBarItem newItem = new NQBarItem(this, itemType, itemKey);

			// Add item to internal hash list
			_bandItems.Add(itemKey, newItem);

			return newItem;
		}

		public bool CreateItemsFromXml(Stream definition)
		{
			try
			{
				// Deserialize XML data from stream
				XmlSerializer serializer = new XmlSerializer(typeof(XmlStub.NQMenuDefinition));
				XmlStub.NQMenuDefinition menudef = (XmlStub.NQMenuDefinition) serializer.Deserialize(definition);

				if (menudef.version == "1.0")
				{
					// Handle main menu reference
					if ((_mainMenuBand != null) && (menudef.menubandref != null))
					{
						IBarBand band = _mainMenuBand;

						// Add all children to band
						AddXmlItemsToBar(band, menudef.menubandref);
					}

					if (menudef.bandref != null)
					{
						// Iterate through band references
						foreach (XmlStub.bandrefType bandref in menudef.bandref)
						{
							if (_bands.ContainsKey(bandref.key))
							{
								IBarBand band = _bands[bandref.key];

								// Process item conditions
								if (bandref.condition != null)
								{
									ProcessBandConditions(bandref);
								}

								// Add all children to band
								AddXmlItemsToBar(band, bandref.baritem);
							}
						}
					}

					if (menudef.band != null)
					{
						// Iterate through band definitions
						foreach (XmlStub.bandType banditem in menudef.band)
						{
							IBarBand band = ProcessBandDef(banditem);
						}
					}

					if (menudef.baritemref != null)
					{
						// Iterate through item references
						foreach (XmlStub.baritemrefType baritemref in menudef.baritemref)
						{
							if (_bandItems.ContainsKey(baritemref.key))
							{
								IBarItem baritem = _bandItems[baritemref.key];

								// Process item conditions
								if (baritemref.condition != null)
								{
									ProcessItemConditions(baritemref);
								}

								// Add all children to item
								AddXmlItemsToBar(baritem, baritemref.baritem);
							}
						}
					}

					if (menudef.baritem != null)
					{
						// Iterate through item definitions
						foreach (XmlStub.baritemType baritem in menudef.baritem)
						{
							ProcessItemDef(baritem);
						}
					}
				}
				else
				{
					return false;
				}

				return true;
			}
			catch (Exception ex)
			{
				// An error occured
				ServiceCore.Log.From(this).OnException(ex).Warning("Could not create items from XML");
				return false;
			}
		}

		public void RemoveItem(string itemKey)
		{
			// Search for the parent of this item and remove it from that parent
			foreach (NQBarBand band in _bands.Values)
			{
				if (band.ItemExists(itemKey))
				{
					band.RemoveItem(itemKey);
					break;
				}
			}
			foreach (NQBarItem item in _bandItems.Values)
			{
				if (item.ItemExists(itemKey))
				{
					item.RemoveItem(itemKey);
					break;
				}
			}

			// Now delete the item itself
			if (_bandItems.ContainsKey(itemKey))
			{
				_bandItems.Remove(itemKey);
			}
		}

		public void RemoveBand(string bandKey)
		{
			// Remove menu entry for the band
			if (_bandItems.ContainsKey("mnuBandList." + bandKey))
			{
				this.RemoveItem("mnuBandList." + bandKey);
			}

			if (_bands.ContainsKey(bandKey))
			{
				_bands.Remove(bandKey);
			}
		}

		public IBarBand CreateBand(string bandKey)
		{
			if (_bands.ContainsKey(bandKey))
			{
				// This item key already exists, throw an exception!
				throw new BarDefinitionException("Bar band with key '" + bandKey + "' already exists.", bandKey);
			}

			NQBarBand barBand = new NQBarBand(this, BarBandType.ToolBand, bandKey);

			// Add band to internal list
			_bands.Add(bandKey, barBand);

			// Add menu entry for the band
			if (_bandItems.ContainsKey("mnuBandList"))
			{
				try
				{
					this.CreateItem("mnuBandList." + bandKey, BarItemType.MenuItem);
					IBarItem listRoot = _bandItems["mnuBandList"];
					listRoot.AddItem("mnuBandList." + bandKey);
				}
				catch (BarDefinitionException ex)
				{
					// Do nothing, the item seems to exist already
					ServiceCore.Log.From(this).Error(ex);
				}
			}

			return barBand;
		}

		public INQStatusBarPanel CreateStatusPanel(string itemKey, string text)
		{
			if (_statusBar == null)
				return null;

			NQStatusBarPanel newPanel = new NQStatusBarPanel(this);
			newPanel.Text = text;

			// Add item to internal hash list
			_statusPanels.Add(itemKey, newPanel);

			// Create a new column in the Grid inside the StatusBar's ItemsPanelTemplate
			// to show the first item expanded on the left and all other items right-aligned.
			//ColumnDefinition coldef = new ColumnDefinition();
			//if (_barHost.StatusBar.Items.Count == 0)
			//{
			//  coldef.Width = new GridLength(10, GridUnitType.Star);
			//}
			//else
			//{
			//  coldef.Width = GridLength.Auto;
			//}
			//_barHost.StatusPanel.Children.Add(coldef);
			_barHost.StatusBarRightItemsPanel.Children.Add(newPanel.StatusBarItem);

			return newPanel;
		}

		public void RemoveStatusPanel(string itemKey)
		{
			if (_statusPanels.ContainsKey(itemKey))
			{
				// Remove the item from StatusBar and its column from StatusBar's ItemsPanelTemplate
				_barHost.StatusBarRightItemsPanel.Children.Remove(_statusPanels[itemKey].StatusBarItem);
				//_barHost.StatusPanel.ColumnDefinitions.RemoveAt(_barHost.StatusPanel.ColumnDefinitions.Count - 1);

				// Remove the panel from internal list
				_statusPanels.Remove(itemKey);
			}
		}

		public IBarBand CreateContextMenu(string bandKey)
		{
			NQBarBand barBand = new NQBarBand(this, BarBandType.ContextMenu, bandKey);

			// Add band to internal list
			_bands.Add(bandKey, barBand);

			return barBand;
		}

		public IBarBand GetBand(string bandKey)
		{
			if (bandKey == "MainMenu")
			{
				return _mainMenuBand;
			}
			else
			{
				return _bands[bandKey];
			}
		}

		public IBarBand GetMenuBand()
		{
			return _mainMenuBand;
		}

		public IBarItem GetItem(string itemKey)
		{
			return (IBarItem) _GetItem(itemKey);
		}

		public INQStatusBarPanel GetStatusPanel(string itemKey)
		{
			return _statusPanels[itemKey];
		}

		public string[] GetBandKeys()
		{
			string[] bandKeys = new string[_bands.Keys.Count];
			_bands.Keys.CopyTo(bandKeys, 0);
			return bandKeys;
		}

		public string[] GetItemKeys()
		{
			string[] itemKeys = new string[_bandItems.Keys.Count];
			_bandItems.Keys.CopyTo(itemKeys, 0);
			return itemKeys;
		}

		public bool ItemExists(string itemKey)
		{
			if (itemKey != null)
			{
				return _bandItems.ContainsKey(itemKey);
			}
			else
			{
				return false;
			}
		}

		public bool BandExists(string bandKey)
		{
			return _bands.ContainsKey(bandKey);
		}

		public void AddBandCondition(string bandKey, BarItemConditionObject condObject, string objectName)
		{
			Dictionary<string, List<IBarItemDependency>> tempdic = null;

			switch (condObject)
			{
				case BarItemConditionObject.Session:
					tempdic = _sessBandList;
					break;

				case BarItemConditionObject.View:
					tempdic = _viewBandList;
					break;
			}

			if (tempdic != null)
			{
				if (!tempdic.ContainsKey(objectName))
				{
					tempdic.Add(objectName, new List<IBarItemDependency>());
				}
				tempdic[objectName].Add(new NQBarItemDependency(bandKey, false));

				// Hide the band, if necessary
				if (_bands.ContainsKey(bandKey))
				{
					_bands[bandKey].HideAlways = true;
				}
			}
		}

		public void AddItemCondition(string itemKey, BarItemConditionObject condObject, string objectName, bool visible)
		{
			Dictionary<string, List<IBarItemDependency>> tempdic = null;

			switch (condObject)
			{
				case BarItemConditionObject.Session:
					tempdic = _sessItemList;
					break;

				case BarItemConditionObject.View:
					tempdic = _viewItemList;
					break;
			}

			if (tempdic != null)
			{
				if (!tempdic.ContainsKey(objectName))
				{
					tempdic.Add(objectName, new List<IBarItemDependency>());
				}
				tempdic[objectName].Add(new NQBarItemDependency(itemKey, visible));

				// Hide the item, if necessary
				if (_bandItems.ContainsKey(itemKey))
				{
					if (!visible)
					{
						_bandItems[itemKey].HideAlways = true;
					}
					else
					{
						_bandItems[itemKey].ItemEnabled = false;
					}
				}
			}
		}

		public IBarItemDependency[] GetBandDependencies(BarItemConditionObject condObject, string objectName)
		{
			IBarItemDependency[] temparray = null;

			Dictionary<string, List<IBarItemDependency>> tempdic = null;

			switch (condObject)
			{
				case BarItemConditionObject.Session:
					tempdic = _sessBandList;
					break;

				case BarItemConditionObject.View:
					tempdic = _viewBandList;
					break;
			}

			if (tempdic != null)
			{
				if (tempdic.ContainsKey(objectName))
				{
					temparray = new IBarItemDependency[tempdic[objectName].Count];
					tempdic[objectName].CopyTo(temparray);
				}
			}

			return temparray;
		}

		public void RemoveBandCondition(string bandKey)
		{
			List<IBarItemDependency> delItems = new List<IBarItemDependency>();

			foreach (List<IBarItemDependency> objDeps in _sessBandList.Values)
			{
				foreach (IBarItemDependency item in objDeps)
				{
					if (item.Key == bandKey)
					{
						// Delete this item
						delItems.Add(item);
					}
				}

				for (int i = 0; i < delItems.Count; i++)
				{
					objDeps.Remove(delItems[i]);
				}
				objDeps.Clear();
			}
			foreach (List<IBarItemDependency> objDeps in _viewBandList.Values)
			{
				foreach (IBarItemDependency item in objDeps)
				{
					if (item.Key == bandKey)
					{
						// Delete this item
						delItems.Add(item);
					}
				}

				for (int i = 0; i < delItems.Count; i++)
				{
					objDeps.Remove(delItems[i]);
				}
				objDeps.Clear();
			}
		}

		public void RemoveItemCondition(string itemKey)
		{
			List<IBarItemDependency> delItems = new List<IBarItemDependency>();

			foreach (List<IBarItemDependency> objDeps in _sessItemList.Values)
			{
				foreach (IBarItemDependency item in objDeps)
				{
					if (item.Key == itemKey)
					{
						// Delete this item
						delItems.Add(item);
					}
				}

				for (int i = 0; i < delItems.Count; i++)
				{
					objDeps.Remove(delItems[i]);
				}
				objDeps.Clear();
			}
			foreach (List<IBarItemDependency> objDeps in _viewItemList.Values)
			{
				foreach (IBarItemDependency item in objDeps)
				{
					if (item.Key == itemKey)
					{
						// Delete this item
						delItems.Add(item);
					}
				}

				for (int i = 0; i < delItems.Count; i++)
				{
					objDeps.Remove(delItems[i]);
				}
				objDeps.Clear();
			}
		}

		public IBarItemDependency[] GetItemDependencies(BarItemConditionObject condObject, string objectName)
		{
			IBarItemDependency[] temparray = null;

			Dictionary<string, List<IBarItemDependency>> tempdic = null;

			switch (condObject)
			{
				case BarItemConditionObject.Session:
					tempdic = _sessItemList;
					break;

				case BarItemConditionObject.View:
					tempdic = _viewItemList;
					break;
			}

			if (tempdic != null)
			{
				if (tempdic.ContainsKey(objectName))
				{
					temparray = new IBarItemDependency[tempdic[objectName].Count];
					tempdic[objectName].CopyTo(temparray);
				}
			}

			return temparray;
		}

		public bool DockTop
		{
			get
			{
				if (_barServiceInit)
				{
					return (_barHost.TlbTrayTop.Visibility == Visibility.Visible);
				}
				else
				{
					return false;
				}
			}
			set
			{
				if (_barServiceInit)
				{
					_barHost.TlbTrayTop.Visibility = (value) ? Visibility.Visible : Visibility.Hidden;
				}
			}
		}

		public bool DockLeft
		{
			get
			{
				if (_barServiceInit)
				{
					return (_barHost.TlbTrayLeft.Visibility == Visibility.Visible);
				}
				else
				{
					return false;
				}
			}
			set
			{
				if (_barServiceInit)
				{
					_barHost.TlbTrayLeft.Visibility = (value) ? Visibility.Visible : Visibility.Hidden;
				}
			}
		}

		public bool DockRight
		{
			get
			{
				if (_barServiceInit)
				{
					return (_barHost.TlbTrayRight.Visibility == Visibility.Visible);
				}
				else
				{
					return false;
				}
			}
			set
			{
				if (_barServiceInit)
				{
					_barHost.TlbTrayRight.Visibility = (value) ? Visibility.Visible : Visibility.Hidden;
				}
			}
		}

		public bool DockBottom
		{
			get
			{
				if (_barServiceInit)
				{
					return (_barHost.TlbTrayBottom.Visibility == Visibility.Visible);
				}
				else
				{
					return false;
				}
			}
			set
			{
				if (_barServiceInit)
				{
					_barHost.TlbTrayBottom.Visibility = (value) ? Visibility.Visible : Visibility.Hidden;
				}
			}
		}

		public object ClientAreaObject
		{
			get
			{
				if (_barHost != null)
				{
					return _barHost.GridClientContainer;
				}
				else
				{
					return null;
				}
			}
		}

		#endregion

		internal BarHost BarHost
		{
			get
			{
				return _barHost;
			}
		}

		internal NQBarItem _GetItem(string itemKey)
		{
			return _bandItems[itemKey];
		}

		internal void SetBandVisibility(NQBarBand band, bool visible)
		{
			if (band.BandType == BarBandType.MenuBand)
			{
				// The menu band is always shown on top
				if (visible && !band.HideAlways)
				{
					_barHost.MenuBarTray.ToolBars.Add(band.ToolBar);
				}
				else
				{
					_barHost.MenuBarTray.ToolBars.Remove(band.ToolBar);
				}

				band.BandVisible = visible;
			}
			else
			{
				ToolBarTray toolBarTray = this.ToolBarTrayFromDirection(band.DockDirection);

				if (visible && !band.HideAlways)
				{
					if (!toolBarTray.ToolBars.Contains(band.ToolBar))
					{
						toolBarTray.ToolBars.Add(band.ToolBar);
					}
				}
				else
				{
					if (toolBarTray.ToolBars.Contains(band.ToolBar))
					{
						toolBarTray.ToolBars.Remove(band.ToolBar);
					}
				}

				// Update the band's menu entry checked state
				if (_bandItems.ContainsKey("mnuBandList." + band.BandKey))
				{
					_bandItems["mnuBandList." + band.BandKey].ItemChecked = visible;
				}

				band.BandVisible = visible;
			}
		}

		internal void SetBandHiddenAlways(NQBarBand band, bool hiddenAlways)
		{
			// Update the band's menu entry checked state
			if (_bandItems.ContainsKey("mnuBandList." + band.BandKey))
			{
				_bandItems["mnuBandList." + band.BandKey].ItemVisible = !band.HideAlways;
			}
		}

		internal void HandleItemClick(NQBarItem senderItem)
		{
			// Band menu entries must control the band's visibility
			if (senderItem.ItemKey.StartsWith("mnuBandList."))
			{
				string extractedBand = senderItem.ItemKey.Substring(12);
				if (_bands.ContainsKey(extractedBand))
				{
					_bands[extractedBand].BandVisible = !senderItem.ItemChecked;
				}
			}

			if (this.ItemClicked != null)
			{
				// Raise global ItemClicked event
				this.ItemClicked(senderItem, new BarItemClickedEventArgs(senderItem));
			}

			// If we are in a container and a view is active, notify the view through a separate method
			if ((_containerService != null) && (_containerService.ViewManager != null))
			{
				IView activeView = _containerService.ViewManager.ActiveView;
				if (activeView != null)
				{
					activeView.BarItemClicked(senderItem);
				}
			}
		}

		internal ToolBarTray ToolBarTrayFromDirection(BandDockDirection dockDirection)
		{
			switch (dockDirection)
			{
				case BandDockDirection.DockTop:
					return _barHost.TlbTrayTop;
				case BandDockDirection.DockBottom:
					return _barHost.TlbTrayBottom;
				case BandDockDirection.DockLeft:
					return _barHost.TlbTrayLeft;
				case BandDockDirection.DockRight:
					return _barHost.TlbTrayRight;
				default:
					return _barHost.TlbTrayLeft;
			}
		}

		internal BandDockDirection DirectionFromToolBarTray(ToolBarTray panel)
		{
			if (panel == _barHost.TlbTrayTop)
			{
				return BandDockDirection.DockTop;
			}
			else if (panel == _barHost.TlbTrayBottom)
			{
				return BandDockDirection.DockBottom;
			}
			else if (panel == _barHost.TlbTrayLeft)
			{
				return BandDockDirection.DockLeft;
			}
			else if (panel == _barHost.TlbTrayRight)
			{
				return BandDockDirection.DockRight;
			}

			return BandDockDirection.DockTop;
		}

		private string SettingCharFromDirection(BandDockDirection dockDirection)
		{
			switch (dockDirection)
			{
				case BandDockDirection.DockTop:
					return "t";
				case BandDockDirection.DockBottom:
					return "b";
				case BandDockDirection.DockLeft:
					return "l";
				case BandDockDirection.DockRight:
					return "r";
				default:
					return "t";
			}
		}

		private BandDockDirection DirectionFromSettingChar(string settingChar)
		{
			switch (settingChar)
			{
				case "t":
					return BandDockDirection.DockTop;
				case "b":
					return BandDockDirection.DockBottom;
				case "l":
					return BandDockDirection.DockLeft;
				case "r":
					return BandDockDirection.DockRight;
				default:
					return BandDockDirection.DockTop;
			}
		}

		private void AddXmlItemsToBar(IBarItemContainer parent, XmlStub.baritemType[] baritems)
		{
			if ((parent != null) && (baritems != null))
			{
				for (int i = 0; i < baritems.Length; i++)
				{
					IBarItem defitem = ProcessItemDef(baritems[i]);
					if (defitem != null)
					{
						if (baritems[i].previousitem != null)
						{
							// Add item after another item
							parent.InsertItem(defitem.ItemKey, baritems[i].previousitem, false);
						}
						else if (baritems[i].nextitem != null)
						{
							// Add item before another item
							parent.InsertItem(defitem.ItemKey, ((baritems[i].nextitem == "{0}") ? null : baritems[i].nextitem), true);
						}
						else
						{
							// Add item at the end of parent menu/band
							parent.AddItem(defitem.ItemKey);
						}
					}
					else
					{
						ServiceCore.Log.From(this).Warning("Could not create item {0} from XML definition.", baritems[i].key);
					}
				}
			}
		}

		private IBarBand ProcessBandDef(XmlStub.bandType banditem)
		{
			IBarBand band = null;
			if (banditem.type == XmlStub.bandtypeDef.contextmenu)
			{
				band = CreateContextMenu(banditem.key);
			}
			else
			{
				band = CreateBand(banditem.key);
			}

			if (banditem.gripSpecified)
				band.ShowGrip = banditem.grip;
			if (banditem.overflowbuttonSpecified)
				band.ShowOverflowButton = banditem.overflowbutton;
			if (banditem.text != null)
			{
				band.DisplayName = banditem.text;
			}
			else
			{
				if (banditem.textres != null)
				{
					band.DisplayName = GetResStringFromDef(banditem.textres);
				}
			}

			// Process item conditions
			if (banditem.condition != null)
			{
				ProcessBandConditions(banditem);
			}

			// Add all children to band
			AddXmlItemsToBar(band, banditem.baritem);

			return band;
		}

		private IBarItem ProcessItemDef(XmlStub.baritemType baritem)
		{
			// Firstly determine item type
			BarItemType itemtype = BarItemType.Button;
			switch (baritem.type)
			{
				case XmlStub.itemtypeDef.button:
					itemtype = BarItemType.Button;
					break;
				case XmlStub.itemtypeDef.checkbox:
					itemtype = BarItemType.CheckBox;
					break;
				case XmlStub.itemtypeDef.radiobutton:
					itemtype = BarItemType.RadioButton;
					break;
				case XmlStub.itemtypeDef.combobox:
					itemtype = BarItemType.ComboBox;
					break;
				case XmlStub.itemtypeDef.dropdown:
					itemtype = BarItemType.DropDownButton;
					break;
				case XmlStub.itemtypeDef.label:
					itemtype = BarItemType.Label;
					break;
				case XmlStub.itemtypeDef.menuitem:
					itemtype = BarItemType.MenuItem;
					break;
				case XmlStub.itemtypeDef.separator:
					itemtype = BarItemType.Separator;
					break;
				case XmlStub.itemtypeDef.splitbutton:
					itemtype = BarItemType.SplitButton;
					break;
				case XmlStub.itemtypeDef.textbox:
					itemtype = BarItemType.TextBox;
					break;
			}

			try
			{
				IBarItem newitem = CreateItem(baritem.key, itemtype);
				newitem.ShowText = false;
				newitem.ShowImage = false;

				// Now set item's properties
				newitem.RightAlign = (baritem.rightalignSpecified && baritem.rightalign);
				if (newitem.ItemType == BarItemType.MenuItem)
				{
					newitem.Keys = baritem.shortcutkeys;
				}

				if (baritem.text != null)
				{
					newitem.ItemText = baritem.text;
					newitem.ShowText = true;
				}
				else
				{
					if (baritem.textres != null)
					{
						newitem.ItemText = GetResStringFromDef(baritem.textres);
						newitem.ShowText = true;
					}
				}

				if (baritem.tooltip != null)
				{
					newitem.ItemToolTip = baritem.tooltip;
				}
				else
				{
					if (baritem.tooltipres != null)
					{
						newitem.ItemToolTip = GetResStringFromDef(baritem.tooltipres);
					}
				}

				if (baritem.imageres != null)
				{
					newitem.ItemImage = this.GetResImageFromDef(baritem.imageres);
					newitem.ShowImage = true;
				}

				if (baritem.showimageSpecified)
				{
					newitem.ShowImage = baritem.showimage;
				}
				if (baritem.showtextSpecified)
				{
					newitem.ShowText = baritem.showtext;
				}

				if (baritem.sizeSpecified)
				{
					newitem.ItemSize = baritem.size;
				}

				// Process item conditions
				if (baritem.condition != null)
				{
					this.ProcessItemConditions(baritem);
				}

				// Set correct visibility
				bool isItemVisible;
				bool isItemDependent = this.IsItemDependent(baritem.key, out isItemVisible);
				if (isItemDependent && !isItemVisible)
				{
					//newitem.ItemVisible = false;
					newitem.HideAlways = true;
				}
				else
				{
					newitem.ItemVisible =
						!_hiddenItems.Contains(newitem.ItemKey) && (!baritem.visibleSpecified || (baritem.visibleSpecified && baritem.visible));
				}
				if (isItemDependent && isItemVisible)
				{
					newitem.ItemEnabled = false;
				}
				else
				{
					newitem.ItemEnabled = (!baritem.enabledSpecified || (baritem.enabledSpecified && baritem.enabled));
				}

				// Run through all children and do the same
				AddXmlItemsToBar(newitem, baritem.baritem);

				// Now return the item object
				return newitem;
			}
			catch (BarDefinitionException ex)
			{
				ServiceCore.Log.From(this).Error(ex);
				return null;
			}
		}

		private void ProcessItemConditions(XmlStub.baritemrefType baritem)
		{
			if (baritem.condition != null)
			{
				foreach (XmlStub.conditionType condition in baritem.condition)
				{
					BarItemConditionObject condObject = BarItemConditionObject.View;
					if (condition.type == AWZhome.NQ.CommonServices.XmlStub.conditionObjectDef.session)
					{
						condObject = BarItemConditionObject.Session;
					}
					else if (condition.type == AWZhome.NQ.CommonServices.XmlStub.conditionObjectDef.view)
					{
						condObject = BarItemConditionObject.View;
					}

					this.AddItemCondition(baritem.key, condObject, condition.name,
						(condition.action != AWZhome.NQ.CommonServices.XmlStub.conditionVisibilityDef.show));
				}
			}
		}

		private void ProcessBandConditions(XmlStub.bandrefType banditem)
		{
			if (banditem.condition != null)
			{
				foreach (XmlStub.conditionType condition in banditem.condition)
				{
					BarItemConditionObject condObject = BarItemConditionObject.View;
					if (condition.type == AWZhome.NQ.CommonServices.XmlStub.conditionObjectDef.session)
					{
						condObject = BarItemConditionObject.Session;
					}
					else if (condition.type == AWZhome.NQ.CommonServices.XmlStub.conditionObjectDef.view)
					{
						condObject = BarItemConditionObject.View;
					}

					this.AddBandCondition(banditem.key, condObject, condition.name);
				}
			}
		}

		private string GetResStringFromDef(string def)
		{
			int lastdelim = def.LastIndexOf('}');
			string resowner = def.Substring(0, lastdelim + 1);
			if (resowner.StartsWith("{") && resowner.EndsWith("}") && (def.Length > (lastdelim + 1)))
			{
				// Load string resource
				IResourceManager resserv = ServiceCore
					.Get<Services.IResourceService>()
					.Instance;
				return resserv.GetResString(resowner.Substring(1, resowner.Length - 2), def.Substring(lastdelim + 1));
			}

			return null;
		}

		private ImageSource GetResImageFromDef(string def)
		{
			int lastdelim = def.LastIndexOf('}');
			string resowner = def.Substring(0, lastdelim + 1);
			if (resowner.StartsWith("{") && resowner.EndsWith("}") && (def.Length > (lastdelim + 1)))
			{
				// Load string resource
				INQResourceGUIManager resserv = ServiceCore
					.Get<Services.IResourceGUIService>()
					.Instance;
				return resserv.GetResImageSource(resowner.Substring(1, resowner.Length - 2), def.Substring(lastdelim + 1));
			}

			return null;
		}

		private bool IsBandDependent(string bandKey)
		{
			// Iterate through all condition lists and search for the band key
			foreach (List<IBarItemDependency> bandlist in _sessBandList.Values)
			{
				for (int i = 0; i < bandlist.Count; i++)
				{
					if (bandlist[i].Key == bandKey)
					{
						return true;
					}
				}
			}
			foreach (List<IBarItemDependency> bandlist in _viewBandList.Values)
			{
				for (int i = 0; i < bandlist.Count; i++)
				{
					if (bandlist[i].Key == bandKey)
					{
						return true;
					}
				}
			}

			// Band not found -> no conditions set for it
			return false;
		}

		private bool IsItemDependent(string itemKey, out bool visible)
		{
			// Iterate through all condition lists and search for the item key
			foreach (List<IBarItemDependency> itemlist in _sessItemList.Values)
			{
				for (int i = 0; i < itemlist.Count; i++)
				{
					if (itemlist[i].Key == itemKey)
					{
						visible = itemlist[i].IsVisible;
						return true;
					}
				}
			}
			foreach (List<IBarItemDependency> itemlist in _viewItemList.Values)
			{
				for (int i = 0; i < itemlist.Count; i++)
				{
					if (itemlist[i].Key == itemKey)
					{
						visible = itemlist[i].IsVisible;
						return true;
					}
				}
			}

			// Item not found -> no conditions set for it
			visible = false;
			return false;
		}
	}

}
